package com.getpebble.android.notifications;

import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.content.SharedPreferences;
import android.os.Build.VERSION;
import android.service.notification.NotificationListenerService;
import android.service.notification.StatusBarNotification;
import com.getpebble.android.common.core.trace.Analytics.MobileAppBehavior;
import com.getpebble.android.common.core.trace.Trace;
import com.getpebble.android.common.core.util.ProcessUtil;
import com.getpebble.android.common.framework.ReadOnlyPreferences;
import com.getpebble.android.framework.notification.PblNotificationProcessor;
import com.getpebble.android.notifications.model.Actions.NotificationDismissKey;
import com.getpebble.android.notifications.model.PblNotification;
import com.getpebble.android.notifications.model.PblNotification.Source;
import com.getpebble.android.notifications.util.NotificationServiceUtil;

@TargetApi(18)
public class PblNotificationService extends NotificationListenerService {
    private static final String TAG = PblNotificationService.class.getSimpleName();
    private static PblNotificationService sService = null;

    public void onCreate() {
        try {
            Trace.verbose(TAG, "onCreate()");
            super.onCreate();
            PblNotificationProcessor.processServiceCreate();
            sService = this;
        } catch (Exception e) {
            Trace.error(TAG, "Error handling notification", e);
            MobileAppBehavior.logNotificationServiceError(TAG, false, e);
        } catch (Throwable t) {
            Trace.error(TAG, "Unrecoverable error occurred handling notification", t);
            MobileAppBehavior.logNotificationServiceError(TAG, true, t);
        }
    }

    @TargetApi(18)
    public void onNotificationPosted(final StatusBarNotification sbn) {
        if (sbn == null) {
            try {
                Trace.warning(TAG, "onNotificationPosted: sbn is null");
            } catch (Exception e) {
                Trace.error(TAG, "Error handling notification", e);
                MobileAppBehavior.logNotificationServiceError(TAG, false, e);
            } catch (Throwable t) {
                Trace.error(TAG, "Unrecoverable error occurred handling notification", t);
                MobileAppBehavior.logNotificationServiceError(TAG, true, t);
            }
        } else {
            Trace.verbose(TAG, "onNotificationPosted(" + sbn + ")");
            NotificationServiceUtil.receivedNotificationFromListenerService();
            ProcessUtil.runWithClearedIdentity(new Runnable() {
                public void run() {
                    PblNotificationProcessor.processNotification(PblNotification.from(sbn, Source.NOTIFICATION));
                }
            });
            Trace.verbose(TAG, "end onNotificationPosted(" + sbn + ")");
        }
    }

    @SuppressLint({"NewApi"})
    public void onNotificationRemoved(final StatusBarNotification sbn) {
        if (sbn == null) {
            try {
                Trace.warning(TAG, "onNotificationPosted: sbn is null");
            } catch (Exception e) {
                Trace.error(TAG, "Error handling notification removal", e);
                MobileAppBehavior.logNotificationServiceError(TAG, false, e);
            } catch (Throwable t) {
                Trace.error(TAG, "Unrecoverable error occurred handling notification", t);
                MobileAppBehavior.logNotificationServiceError(TAG, true, t);
            }
        } else {
            String key;
            Trace.verbose(TAG, "onNotificationRemoved(" + sbn + ")");
            if (VERSION.SDK_INT >= 20) {
                key = sbn.getKey();
            } else {
                key = null;
            }
            ProcessUtil.runWithClearedIdentity(new Runnable() {
                public void run() {
                    PblNotificationProcessor.processNotificationRemoval(sbn.getId(), sbn.getTag(), sbn.getPackageName(), key);
                }
            });
        }
    }

    @SuppressLint({"NewApi"})
    public static void dismissNotification(NotificationDismissKey key) {
        try {
            PblNotificationService service = sService;
            if (service == null) {
                Trace.debug(TAG, "Cannot cancel notification, service is null");
            } else if (VERSION.SDK_INT >= 21) {
                service.cancelNotification(key.mKey);
            } else {
                service.cancelNotification(key.mPackageName, key.mTag, key.mId);
            }
        } catch (Exception e) {
            Trace.error(TAG, "Error in onDestroy", e);
            MobileAppBehavior.logNotificationServiceError(TAG, false, e);
        } catch (Throwable t) {
            Trace.error(TAG, "Unrecoverable error occurred handling notification", t);
            MobileAppBehavior.logNotificationServiceError(TAG, true, t);
        }
    }

    public void onDestroy() {
        try {
            Trace.verbose(TAG, "onDestroy()");
            sService = null;
            super.onDestroy();
        } catch (Exception e) {
            Trace.error(TAG, "Error in onDestroy", e);
        } catch (Throwable t) {
            Trace.error(TAG, "Unrecoverable error occurred", t);
        }
    }

    public SharedPreferences getSharedPreferences(String name, int mode) {
        try {
            return new ReadOnlyPreferences(getApplicationContext(), name);
        } catch (Exception e) {
            Trace.error(TAG, "Error returning shared preferences reference", e);
            MobileAppBehavior.logNotificationServiceError(TAG, false, e);
            return null;
        } catch (Throwable t) {
            Trace.error(TAG, "Unrecoverable error occurred handling notification", t);
            MobileAppBehavior.logNotificationServiceError(TAG, true, t);
        }
    }
}
